package org.ziegler.log.analysis;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.ziegler.log.analysis.cmdParser.CmdOptionParser;
import org.ziegler.log.analysis.cmdParser.FilterType;
import org.ziegler.log.analysis.cmdParser.ResultFilterType;
import org.ziegler.log.analysis.cmdParser.ShowType;
import org.ziegler.log.analysis.core.FileUtils;
import org.ziegler.log.analysis.core.LogProcess;
import org.ziegler.log.analysis.fileFilter.AllFileFilter;
import org.ziegler.log.analysis.fileFilter.CachedFileFilter;
import org.ziegler.log.analysis.fileFilter.DateFilterFilter;
import org.ziegler.log.analysis.fileFilter.EmptyFileFilter;
import org.ziegler.log.analysis.fileFilter.FileFilter;
import org.ziegler.log.analysis.resultFilter.ResultDateFilter;
import org.ziegler.log.analysis.resultFilter.ResultFilter;
import org.ziegler.log.analysis.resultFilter.ServerIdResultFilter;
import org.ziegler.log.analysis.resultHandler.AllResultHandler;
import org.ziegler.log.analysis.resultHandler.CacheErrResultHandler;
import org.ziegler.log.analysis.resultHandler.DefaultResultHandler;
import org.ziegler.log.analysis.resultHandler.ErrKeyResultHandler;
import org.ziegler.log.analysis.resultHandler.LastErrResultHandler;
import org.ziegler.log.analysis.resultHandler.LimitResultHandler;
import org.ziegler.log.analysis.resultHandler.ResultHandler;
import org.ziegler.log.analysis.resultHandler.UnknownErrResultHandler;

public class AppMain {
    public static void main(String[] args) {

        final Logger logger = LogManager.getLogger("HelloWorld");
        logger.info("Hello, World!");

        AppMain appMain = new AppMain();
        appMain.run(args);
    }

    public void run(String[] args) {
        AppConfig.getInstance().init();

        CmdOptionParser.getInstance().parse(args);

        // 显示帮助
        if (CmdOptionParser.getInstance().isHelp()) {
            CmdOptionParser.getInstance().printHelpOn();
        }

        // 初始化日志文件路径
        if (initPath()) return;

        // 初始化线程池数量
        initThreadNum();

        if (CmdOptionParser.getInstance().hasFilter()
                && CmdOptionParser.getInstance().hasShow()) {
            // 初始化文件过滤器
            final FileFilter fileFilter = initFileFilter();

            // 构造Process
            final LogProcess logProcess = new LogProcess(fileFilter);

            // 结果过滤器
            List<ResultFilter> resultFilters = initResultFilters();
            for (ResultFilter resultFilter : resultFilters) {
                logProcess.addResultFilter(resultFilter);
            }

            // 初始化ResultHandler
            List<ResultHandler> resultHandlers = initResultHandlers();
            for (ResultHandler resultHandler : resultHandlers) {
                logProcess.addResultHandler(resultHandler);
            }

            // 并发计算（运行）
            logProcess.run();
        }

        LogCore.info("程序已经结束");
    }

    private List<ResultFilter> initResultFilters() {

        List<ResultFilter> result = new ArrayList<>();

        final List<ResultFilterType> resultFilterTypes = CmdOptionParser.getInstance().getResultFilterTypes();
        for (ResultFilterType resultFilterType : resultFilterTypes) {
            switch (resultFilterType) {
                case DATETIME:
                    String datetime = CmdOptionParser.getInstance().getDateTime();
                    LocalDateTime beginDateTime = DateFilterFilter.toDateTime(datetime);
                    ResultDateFilter resultDateFilter = new ResultDateFilter(beginDateTime);
                    result.add(resultDateFilter);
                    break;
                case SERVER_ID:
                    // 服务器区过滤
                    final int serverId = CmdOptionParser.getInstance()
                            .getServerId();
                    ServerIdResultFilter serverIdResultFilter
                            = new ServerIdResultFilter(serverId);
                    result.add(serverIdResultFilter);
                    break;
                default:
            }
        }

        return result;
    }

    private List<ResultHandler> initResultHandlers() {
        List<ResultHandler> resultHandlers = new ArrayList<>();
        // 4. 计算
        final List<ShowType> show = CmdOptionParser.getInstance().getShowTypes();
        if (show.size() == 0) {
            resultHandlers.add(new DefaultResultHandler());
        } else {
            for (ShowType showType : show) {
                switch (showType) {
                    case ALL:
                        resultHandlers.add(new AllResultHandler());
                        break;
                    case LAST_ERR:
                        resultHandlers.add(new LastErrResultHandler());
                        break;
                    case FILTER_ERR:
                        final List<String> errorKeyList = CmdOptionParser.getInstance().getAllErrKey();
                        for (String errKey : errorKeyList) {
                            resultHandlers.add(new ErrKeyResultHandler(errKey));
                        }
                        break;
                    case UNKNOWN_ERR:
                        resultHandlers.add(new UnknownErrResultHandler());
                        break;
                    case CACHE:
                        // 是否缓存
                        final boolean cache = CmdOptionParser.getInstance().hasCache();
                        resultHandlers.add(new CacheErrResultHandler(cache));
                        break;
                    case LIMIT:
                        final int limit = CmdOptionParser.getInstance()
                                .getLimit();
                        resultHandlers.add(new LimitResultHandler(limit));
                        break;
                    case EMPTY:
                        break;
                    default:
                        LogCore.error("Unknown showType = " + showType);
                }
            }
        }
        return resultHandlers;
    }

    private FileFilter initFileFilter() {
        // 3. 文件过滤器处理
        FileFilter fileFilter = new EmptyFileFilter();
        if (CmdOptionParser.getInstance().hasFilter()) {
            final FilterType filterType = CmdOptionParser.getInstance().getFilterType();

            switch (filterType) {
                case ALL:
                    fileFilter = new AllFileFilter();
                    break;
                case CACHE:
                    // 是否缓存
                    final boolean cache = CmdOptionParser.getInstance().hasCache();
                    fileFilter = new CachedFileFilter(cache);
                    break;
                case DATETIME:
                    String datetime = CmdOptionParser.getInstance().getDateTime();
                    LocalDateTime afterDatetime = DateFilterFilter.toDateTime(datetime);
                    fileFilter = new DateFilterFilter(afterDatetime);
                    break;
                default:
                    LogCore.error("异常的filterType = " + filterType);
            }
        }
        return fileFilter;
    }

    private void initThreadNum() {
        // 2. 设置执行线程数量
        if (CmdOptionParser.getInstance().hasThreadNum()) {
            final int threadNum = CmdOptionParser.getInstance().getThreadNum();
            AppConfig.getInstance().setThreadPoolNum(threadNum);

            LogCore.info("设置启动线程池数量threadNum = " + threadNum);
        }


    }

    private boolean initPath() {
        // 1. 设置日志文件路径
        if (CmdOptionParser.getInstance().hasPath()) {
            final String path = CmdOptionParser.getInstance().getPath();
            AppConfig.getInstance().setLogPath(path);

            LogCore.info("设置日志文件路径path = " + path);
        }

        final String logPath = AppConfig.getInstance().getLogPath();
        if (!FileUtils.exists(logPath)) {
            LogCore.error("无效的日志文件path = " + logPath);
            return true;
        }

        return false;
    }


}
